﻿using Rhino;
using Rhino.Commands;
using Rhino.DocObjects;
using Rhino.Geometry;
using Rhino.Input;
using Rhino.Input.Custom;
using System;
using System.Collections.Generic;
using System.Drawing;

namespace YangTools.Realization
{
    /// <summary>
    /// 表示复制模式的枚举
    /// </summary>
    public enum Operator
    {
        /// <summary>
        /// 乘 模式，使用整型 0 表示
        /// </summary>
        Multiply = 0,

        /// <summary>
        /// 除 模式，使用整型 1 表示
        /// </summary>
        divide = 1
    }

    /// <summary>
    /// SUCopy 命令：像SU的复制一样进行阵列
    /// </summary>
    class SUCopy
    {
        /// <summary>
        /// 线框显示模式
        /// </summary>
        public readonly Rhino.Display.DisplayModeDescription wireframeMode = Rhino.Display.DisplayModeDescription.FindByName("Wireframe");

        /// <summary>
        /// 复制的模式，默认为 除 -- 1
        /// </summary>
        private Operator Operator = Operator.divide;

        /// <summary>
        /// 复制个数，默认为 3
        /// </summary>
        private int Count = 3;

        /// <summary>
        /// 要被复制的原始物体
        /// </summary>
        private List<RhinoObject> originalObjects = new List<RhinoObject>();

        /// <summary>
        /// 复制后的得到的物体
        /// </summary>
        private List<RhinoObject> copiedObjects = new List<RhinoObject>();

        /// <summary>
        /// 复制的起点
        /// </summary>
        private Point3d startPoint;

        /// <summary>
        /// 复制的终点
        /// </summary>
        private Point3d endPoint;



        /// <summary>
        /// 指令调用的主方法
        /// </summary>
        /// <param name="doc">当前的犀牛文档</param>
        /// <param name="mode"></param>
        /// <returns></returns>
        internal Result Copy()
        {
            //GetObjects();
            originalObjects = RhinoHelper.Selection.GetObjects("请选择要复制的物体：");
            if (originalObjects.Count == 0) return Result.Cancel;

            var pointResult = RhinoHelper.UserInterface.GetPoint("请选择复制的起点：");
            if (pointResult.Count == 0)
            {
                return Result.Cancel;
            }
            else
            {
                startPoint = pointResult[0];
            }

            pointResult = RhinoHelper.UserInterface.GetPoint("请选择复制的终点：", GetEndPoint_DynamicDraw);
            if (pointResult.Count == 0)
            {
                return Result.Cancel;
            }
            else
            {
                endPoint = pointResult[0];
            }


            var viewTable = RhinoDoc.ActiveDoc.Views;

            while (true)
            {
                viewTable.RedrawEnabled = false;
                ClearCopied(); // 删除老的
                CopyObjects(); // 复制新的

                viewTable.RedrawEnabled = true;
                viewTable.Redraw();


                GetResult strResult;
                string ope = Operator == Operator.Multiply ? "*" : "/";
                string resultString = RhinoHelper.UserInterface.GetString($"请输入要复制的个数 <{ope}{Count}>：", out strResult);

                if (strResult == GetResult.Cancel)
                {
                    // 使用Esc取消的情况
                    ClearCopied();
                    return Result.Cancel;
                }

                // 直接回车的情况
                if (resultString == "")
                {
                    break;
                }
                // 输入了 / ，尝试除法
                else if (resultString.Contains("/"))
                {
                    resultString = resultString.Replace("/", "");
                    try
                    {
                        Count = int.Parse(resultString);
                        Operator = Operator.divide;
                    }
                    catch (FormatException)
                    {
                        RhinoApp.WriteLine("输入的乘除格式不正确");
                        ClearCopied();
                        return Result.Failure;
                    }
                }
                // 输入了 * ，尝试乘法
                else if (resultString.Contains("*"))
                {
                    resultString = resultString.Replace("*", "");
                    try
                    {
                        Count = int.Parse(resultString);
                        Operator = Operator.Multiply;
                    }
                    catch (FormatException)
                    {
                        RhinoApp.WriteLine("输入的乘除格式不正确");
                        ClearCopied();
                        return Result.Failure;
                    }
                }
                // 输入了纯数字，尝试默认乘除
                else
                {
                    try
                    {
                        Count = int.Parse(resultString);
                    }
                    catch (FormatException)
                    {
                        RhinoApp.WriteLine("输入的乘除格式不正确");
                        ClearCopied();
                        return Result.Failure;
                    }
                }
            }

            ShowDefaultDisplayMode();
            SeclectAll();
            viewTable.Redraw();

            return Result.Success;
        }

        private void SeclectAll()
        {
            foreach (var item in originalObjects)
            {
                item.Select(true);
            }
            foreach (var item in copiedObjects)
            {
                item.Select(true);
            }
        }

        /// <summary>
        /// 将复制的物体设置回默认的显示模式
        /// </summary>
        private void ShowDefaultDisplayMode()
        {
            if (copiedObjects.Count == 0) return;

            foreach (RhinoObject obj in copiedObjects)
            {
                obj.Attributes.RemoveDisplayModeOverride();
                obj.CommitChanges();
            }
        }

        /// <summary>
        /// 从犀牛中获取物体
        /// </summary>
        /// <returns>
        /// List<RhinoObject> 由RhinoObject组成的集合，如果没有选中物体，将返回一个个数为0的空集合
        /// </returns>
        private void GetObjects()
        {

            GetObject getObjects = new GetObject();
            getObjects.SetCommandPrompt("选择要复制的物体："); // 设置命令行提示字符

            // 使用 GetMultiple 而不是 Get 可以允许用户选择多个物体，并且可以预选
            var getResult = getObjects.GetMultiple(1, 0);
            if (getResult != GetResult.Object) return;

            foreach (var item in getObjects.Objects())
            {
                originalObjects.Add(item.Object());
            }
            getObjects.Dispose();
        }

        /// <summary>
        /// 获取复制的起点或终点
        /// </summary>
        /// <param name="point">获取到的点要存储在哪里</param>
        /// <param name="message">命令行提示信息</param>
        /// <param name="dynamicDraw">是否在获取点时动态绘制</param>
        /// <returns>获取结果</returns>
        private GetResult GetPoint(ref Point3d point, string message, EventHandler<GetPointDrawEventArgs> dynamicDraw)
        {
            GetPoint getPoint = new GetPoint();
            if (message != null) getPoint.SetCommandPrompt(message);
            if (dynamicDraw != null) getPoint.DynamicDraw += dynamicDraw;

            GetResult getResult = getPoint.Get();
            if (getResult == GetResult.Point)
            {
                point = getPoint.Point();
            }
            getPoint.Dispose();
            return getResult;
        }

        /// <summary>
        /// 用于预览选择复制的终点时的复制结果
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GetEndPoint_DynamicDraw(object sender, GetPointDrawEventArgs e)
        {
            e.Display.DrawLine(startPoint, e.CurrentPoint, Color.White, 1);

            Vector3d vectorBase = e.CurrentPoint - startPoint;
            for (int i = 1; i < Count + 1; i++)
            {
                var a = Convert.ToDouble(i) / Math.Pow(Count, (int)Operator); // 通过数学计算得到每一次复制的向量的系数
                var t = Transform.Translation(a * vectorBase);
                foreach (var obj in originalObjects)
                {
                    e.Display.DrawObject(obj, t);
                }
            }
        }

        /// <summary>
        /// 对物体进行复制
        /// </summary>
        private void CopyObjects()
        {
            Vector3d vectorBase = endPoint - startPoint;
            var objectTable = RhinoDoc.ActiveDoc.Objects;

            for (int i = 1; i < Count + 1; i++)
            {
                var a = Convert.ToDouble(i) / Math.Pow(Count, (int)Operator); // 通过数学计算得到每一次复制的向量的系数
                var t = Transform.Translation(a * vectorBase);

                foreach (RhinoObject obj in originalObjects)
                {
                    Guid copyId = objectTable.Transform(obj.Id, t, false);
                    RhinoObject copyObject = objectTable.FindId(copyId);
                    copyObject.Attributes.SetDisplayModeOverride(wireframeMode);
                    copyObject.CommitChanges();
                    copiedObjects.Add(copyObject);
                }
            }
        }

        /// <summary>
        /// 删除上一次复制的物体
        /// </summary>
        private void ClearCopied()
        {
            if (copiedObjects.Count == 0) return;

            foreach (var item in copiedObjects)
            {
                //RhinoDoc.ActiveDoc.Objects.Delete(item);
                RhinoDoc.ActiveDoc.Objects.Purge(item);
            }
            copiedObjects.Clear();
        }
    }
}





